package adm.util;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.TextPaint;
import android.util.TypedValue;
import android.view.MotionEvent;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;

public class OverlayElementMap extends ItemizedOverlay {
    private int markerHeight;
    private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
    public boolean isTapped = false;
    private int index;
    private MapController mapController;
    private Context context;

    private int FONT_SIZE;
    private int TITLE_MARGIN;

    public OverlayElementMap(Drawable defaultMarker, Context context)
    {
        /*Calling boundCenterBottom() on defaultMarker makes the marker image connect
          at its Bottom center to the latitude and longitude of this Overlay Item*/
        super(boundCenterBottom(defaultMarker));

        markerHeight = ((BitmapDrawable) defaultMarker).getBitmap().getHeight();
        this.context = context;
        FONT_SIZE = (int) getValue(14f);
        TITLE_MARGIN = (int) getValue(8f);

        /* This call to populate is important. Although this does not appear in the MapView tutorial
         * on Google's Android developer site, the mapview some times crashes without this call.
         */
        populate();
    }
    
    public OverlayElementMap(Drawable defaultMarker, MapController mapController, Context context)
    {
        /*Calling boundCenterBottom() on defaultMarker makes the marker image connect
          at its Bottom center to the latitude and longitude of this Overlay Item*/
        super(boundCenterBottom(defaultMarker));

        markerHeight = ((BitmapDrawable) defaultMarker).getBitmap().getHeight();
        this.mapController = mapController;
        this.context = context;
        FONT_SIZE = (int) getValue(14f);
        TITLE_MARGIN = (int) getValue(8f);

        /* This call to populate is important. Although this does not appear in the MapView tutorial
         * on Google's Android developer site, the mapview some times crashes without this call.
         */
        populate();
    }

    @Override
    protected OverlayItem createItem(int i)
    {
        return mOverlays.get(i);
    }

    @Override
    public int size()
    {
        return mOverlays.size();
    }

    @Override
    public void draw(android.graphics.Canvas canvas, MapView mapView,
            boolean shadow)
    {
        super.draw(canvas, mapView, false);
        
        if (!isTapped) {
        	// go through all OverlayItems and draw title for each of them
        	OverlayItem item = mOverlays.get(index);
        	
        	/* Converts latitude & longitude of this overlay item to coordinates on screen.
        	 * As we have called boundCenterBottom() in constructor, so these coordinates
        	 * will be of the bottom center position of the displayed marker.
        	 */
        	GeoPoint point = item.getPoint();
        	Point markerBottomCenterCoords = new Point();
        	mapView.getProjection().toPixels(point, markerBottomCenterCoords);

        	TextPaint paintText = new TextPaint();
        	Paint paintRect = new Paint();

        	/* Find the width and height of the title*/
        	Rect rect = new Rect();
        	paintText.setTextSize(FONT_SIZE);
        	paintText.getTextBounds(item.getTitle(), 0, item.getTitle().length(), rect);

        	rect.inset(-TITLE_MARGIN, -TITLE_MARGIN);
			if (!item.getSnippet().equals("metro"))
				rect.offsetTo(markerBottomCenterCoords.x - rect.width()/2, markerBottomCenterCoords.y - markerHeight - rect.height());
			else rect.offsetTo(markerBottomCenterCoords.x - rect.width()/2, markerBottomCenterCoords.y - markerHeight);
			
        	paintText.setTextAlign(Paint.Align.CENTER);
        	paintText.setTextSize(FONT_SIZE);
        	paintText.setAntiAlias(true);
        	paintText.setFakeBoldText(true); 
        	paintText.setARGB(255, 255, 255, 255);
        	paintRect.setARGB(120, 0, 0, 0);
        	paintRect.setAntiAlias(true);

        	canvas.drawRoundRect( new RectF(rect), 8, 8, paintRect);
        	canvas.drawText(item.getTitle(), rect.left + rect.width() / 2,
        			rect.bottom - TITLE_MARGIN, paintText);
        }
    }

    public void addOverlay(int latitude, int longitude, String title,
            String snippet)
    {
        OverlayItem item;

        GeoPoint geopoint = new GeoPoint(latitude, longitude);
        item = new OverlayItem(geopoint, title, snippet);
        mOverlays.add(item);
        populate();

    }

    public void addOverlay(OverlayItem overlayItem)
    {
        mOverlays.add(overlayItem);
        populate();
    }
    
    @Override
   	public boolean onTap(GeoPoint point, MapView mapView) {
       	if (super.onTap(point, mapView))
       		return true;
       	else isTapped = true;
       	return true;
    }
    
    @Override
	public boolean onTap(int index) {
    	OverlayItem item = mOverlays.get(index);
    	
    	if (!item.getSnippet().equals("start") && !item.getSnippet().equals("end")) {
    		if (index == this.index) {
    			if (isTapped == false)
    				isTapped = true;
    			else {
    				isTapped = false;
    				mapController.animateTo(item.getPoint());
    			}
    		}
    		else if (isTapped == true) {
    			isTapped = false;
    			mapController.animateTo(item.getPoint());
    		}
    		else mapController.animateTo(item.getPoint());
    	}
    	
    	this.index = index;
    	
    	return true;
    }
    
    public void setIndex(int index) {
    	this.index = index;
    }
    
    public float getValue(float value) {
		float v = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 
				(float) value, context.getResources().getDisplayMetrics());
		return v;
	}
}